<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
	/**
	 * CodeIgniter
	 *
	 * An open source application development framework for PHP 4.3.2 or newer
	 *
	 * @package		CodeIgniter
	 * @author		ExpressionEngine Dev Team
	 * @copyright	Copyright (c) 2008 - 2009, EllisLab, Inc.
	 * @license		http://codeigniter.com/user_guide/license.html
	 * @link		http://codeigniter.com
	 * @since		Version 1.0
	 * @filesource
	 */
	// ------------------------------------------------------------------------
	
	/**
	 * @package		CodeIgniter
	 * @subpackage	Libraries
	 * @author		AnhDT
	 */
	
	require_once APP_LIBRARY_PATH . 'tree/menu/parser/st_menu_query_parser_interface.php';
	require_once APP_LIBRARY_PATH . 'tree/menu/parser/st_menu_abstract_parser.php';
	class st_menu_query_parser extends st_menu_abstract_parser implements st_menu_query_parser_interface {
		const MENU_MIN_LEVEL = 0;
		protected static $_database = null;
		protected $_query           = '';
		protected $_privateKeyName  = '';
		protected $_parentKeyName   = '';
		/**Xác định level để xây dựng đệ quy cấu trúc menu nhanh nhất*/
		protected $_levelSpecName   = 'level';
		
		/** Hàm khởi tạo */
		public function __construct($_query = '', $_privateKeyName = '', $_parentKeyName = '') {
			$this->getDatabase();
			$this->factory($_query, $_privateKeyName, $_parentKeyName);
		}
		
		/**Tạo một bộ phân tích câu lệnh truy vấn*/
		public function factory($_query = '', $_privateKeyName = '', $_parentKeyName = '') {
			if (!empty($_query)) {
				$this->setQuery($_query);
				$this->parseQuery($_query);
			}
			if (!empty($_privateKeyName)) {
				$this->_privateKeyName = $_privateKeyName;
			}
			if (!empty($_parentKeyName)) {
				$this->_parentKeyName = $_parentKeyName;
			}
			return $this;	
		}
		
		/**Phân giải câu truy vấn*/
		public function parseQuery($_query = '') {
			if (!$this->checkConditionBeforeParse()) {
				return false;	
			}
			if (empty($_query)) {
				$_query = & $this->_query;	
			} else {
				if (empty($this->_query)) {
					$this->_query = & $_query;	
				}	
			}
			$_query .= ' ORDER BY `' . $this->getLevelSpecName() . '`';
			if (!class_exists('st_menu')) {
				$CI = & get_instance();
				$CI->load->library('tree/menu/st_menu');
				unset($CI->st_menu);
			}
			$_database   = & self::$_database;
			$_menu       = & $this->getMenu();
			$_privateKey = $this->_privateKeyName;
			$_parentKey  = $this->_parentKeyName;
			$_menu->resetChildren();
			$_queryDB = $_database->query($_query);
			$_attributes = array('id', 'title', 'name', 'url', 'tootip');
			foreach ($_queryDB->result() as $_menuStdItem) {
				$_menuItem = new st_menu();
				foreach ($_attributes as $_attribute) {
					if (isset($_menuStdItem->$_attribute)) {
						$_method = 'set' . ucfirst($_attribute);
						$_menuItem->$_method($_menuStdItem->$_attribute);	
					}
				}
				if (($_parentId = $_menuStdItem->$_parentKey) != null) {
					if ($_menu->hasChild($_parentId)) {
						$_menu->getChild($_parentId)->addChild($_menuItem);
					} else {
						$_found = false;
						if ($_menu->countChildren() > 0) {
							foreach ($_menu->getChildren() as $_childMenu) {
								$this->addMenuItemRecursive($_childMenu, $_menuItem, $_parentId, $_found);
							}
						}
						if ($_menuItem->getLevel() === self::MENU_MIN_LEVEL) {
							$_menu->addChild($_menuItem);	
						}
					}
				}
			}
			$_queryDB->free_result();
			unset($_privateKey, $_parentKey, $_attributes, $_queryDB);
			return $this;
		}
		
		/**Thêm menu con một cách đệ quy*/
		public function & addMenuItemRecursive(& $_parent, & $_child, $_parentId, $_found) {
			$_found = true;
			if ($_parent->hasChild($_parentId)) {
				$_parent->getChild($_parentId)->addChild($_child);
				return $_found;
			} else {
				if ($_parent->countChildren() > 0) {
					foreach ($_parent->getChildren() as $_childMenu) {
						$this->addMenuItemRecursive($_childMenu, $_child, $_parentId, $_found);
					}
				}
			}
			return $_found;
		}
		
		/*Kiểm tra điều kiện cần thiết trước khi phân giải**/
		public function checkConditionBeforeParse() {
			if (empty($this->_privateKeyName) || empty($this->_parentKeyName) || empty(self::$_database) || empty($this->_levelSpecName)) {
				return false;																								  			}	
			return true;
		}
		
		/**Thiết lập câu lệnh truy vấn*/
		public function setQuery($_query = '') {
			if (empty($_query)) {
				return false;
			}
			$this->_query = (string)$_query;
			return $this;
		}
		
		/**Lấy về câu lệnh truy vấn*/
		public function getQuery() {
			return $this->_query;
		}
		
		/**Đặt tên cho khóa chính của đối tượng menu*/
		public function setPrivateKeyName($_privateKeyName = '') {
			if (empty($_privateKeyName)) {
				return false;
			}
			$this->_privateKeyName = (string)$_privateKeyName;
			return $this;
		}
		
		/**Lấy về tên khóa chính*/
		public function getPrivateKeyName() {
			return $this->_privateKeyName;
		}
		
		/**Đặt tên khóa cha*/
		public function setParentKeyName($_parentKeyName = '') {
			if (empty($_parentKeyName)) {
				return false;
			}
			$this->_parentKeyName = (string)$_parentKeyName;
			return $this;
		}
		
		/**Lấy về tên khóa cha*/
		public function getParentKeyName() {
			return $this->_parentKeyName;
		}
		
		/**Đặt tên khóa cha*/
		public function setLevelSpecName($_levelSpecName = '') {
			if (empty($_levelSpecName)) {
				return false;
			}
			$this->_levelSpecName = (string)$_levelSpecName;
			return $this;
		}
		
		/**Lấy về tên trường level để xác định cấp độ menu*/
		public function getLevelSpecName() {
			return $this->_levelSpecName;
		}
		
		/**Lấy về cơ sở dữ liệu*/
		public static function getDatabase() {
			if (null === self::$_database) {
				$CI = & get_instance();
				if (!empty($CI)) {
					if (!class_exists('CI_DB_mysql_driver')) {
						$CI->load->database();	
					}
				} else {
					return false;	
				}
				self::$_database = & $CI->db;	
			}	
			return self::$_database;
		}	
		
		/**Reset lại toàn bộ thông tin*/
		public function reset() {
			parent::reset();
			$this->_query           = '';
			$this->_privateKeyName  = '';
			$this->_parentKeyName   = '';
			$this->_levelSpecName   = 'level';		
			return $this;
		}
	}
?>
	